﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Cqrs.Infrastructure.Database;

namespace Cqrs.Infrastructure
{
    public interface IHandlesEvent<T>
    {
        void Handle(T message);
    }

    public class EventPublisher : IEventPublisher
    {
        private readonly Dictionary<Type, List<Action<Event>>> _events = new Dictionary<Type, List<Action<Event>>>();
        public bool SynchronousPublishing { get; set; }

        public void RegisterHandler<T>(Action<T> handler) where T : Event
        {
            List<Action<Event>> handlers;
            if (!_events.TryGetValue(typeof(T), out handlers))
            {
                handlers = new List<Action<Event>>();
                _events.Add(typeof(T), handlers);
            }
            handlers.Add(DelegateAdjuster.CastArgument<Event, T>(x => handler(x)));
        }

        public void Publish<T>(T @event) where T : Event
        {
            List<Action<Event>> handlers;
            if (!_events.TryGetValue(@event.GetType(), out handlers)) return;
            foreach (var handler in handlers)
            {
                //dispatch on thread pool for added awesomeness
                var handler1 = handler;
                if (SynchronousPublishing)
                    handler1(@event);
                else
                    ThreadPool.QueueUserWorkItem(x => handler1(@event));
               
            }
        }
    }
}
